#include <iostream>
#include <mutex>
//单例：一个类只有一个实例化对象

//饿汉模式：以空间换时间
// class Singleton
// {
//     private:
//         static Singleton _eton;

//         Singleton():_data(99) {
//             std::cout << "单例对象构造！"<< std::endl;
//         }
//         Singleton(const Singleton&) = delete;
//         ~Singleton(){}
//     private:
//         int _data;
//     public:
//         static Singleton& getInstance()
//         {
//             return _eton;
//         }
//         int getData()
//         {
//             return _data;
//         }
// };
// Singleton Singleton::_eton;//调用构造函数实例化，程序运行的时候就已经创建了


//懒汉方式：懒加载--一个对象在用的时候再进行实例化
// class Singleton
// {
//     private:
//         Singleton():_data(99)
//         {
//             std::cout << "单例对象构造!\n";
//         }
//         Singleton(const Singleton&) = delete;
//         ~Singleton(){}
//     private:
//         int _data;
//     public:
//         //如果多个线程试图同时初始化同一个局部变量，则初始化只发生一次--C++11
//         static Singleton& getInstance()//用的时候再实例化
//         {
//             static Singleton _eton;
//             return _eton;
//         }
//         int getData()
//         {
//             return _data;
//         }
// };

class Singleton
{
private:
    static Singleton* instance;
    int _data;
    static std::mutex mutex;//用于线程安全

    Singleton():_data(99) {
        std::cout << "单例对象构造!" << std::endl;
    } 
public:
    static Singleton* getInstance()
    {
        //双重检查锁的目的之一就是为了优化性能，避免在实例已经存在的情况下不必要地进入临界区并竞争锁。
        //一旦实例创建完成，后续的调用可以非常高效地返回已创建的实例，而不会引入额外的锁竞争开销
        if(instance == nullptr)//实例已创建，则直接返回
        {
            std::lock_guard<std::mutex> lock(mutex);//RAII,构造时加锁，析构时释放互斥锁
            if(instance == nullptr)
            {
                instance = new Singleton();
            }
        }
        return instance;
    }

    int getData()
    {
        return _data;
    }
};

Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mutex;

int main()
{
    //std::cout << Singleton::getInstance().getData() << std::endl;
    Singleton* singleton = Singleton::getInstance();
    std::cout << singleton->getData() << std::endl;

    return 0;
}
